Retrofit源码分析

Retrofit源码分析

基于Retrofit2.1.的源码分析,Retrofit的用例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();

public interface MyApi
{
@GET('/xx/xx')
Call<User> getUser();
}

MyApi api = retrofit.create(MyApi.class);
Response<User> user = api.getUser().execute();

参数配置

Retrofit使用了Builder的方式来配置参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static final class Builder {
private final Platform platform;
private okhttp3.Call.Factory callFactory;
private HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories = new ArrayList<>();
private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
private Executor callbackExecutor;
private boolean validateEagerly;

public Builder() {
this(Platform.get());
}

Builder(Platform platform) {
this.platform = platform;
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
}

Retrofit配置的参数:

platform指定了Retrofit使用的平台,可以为Android或者Java8。在不同平台使用了不同的callAdapter以及CallbackExecutor,前者负责转换OkHttpCall为该平台下的Call请求,CallbackExecutor负责将请求投递出去。

callFactory 即Call的工厂类,通过该工厂类可以生成Call对象,这个Call是什么呢?它如下描述所说

A call is a request that has been prepared for execution,A call can be canceled. As this object represents a single request/response pair (stream), it cannot be executed twice

Call封装了我们的HTTP请求,它可以被执行调用并返回结果,这样使得http请求对外界来说是透明的,它也是个请求/响应对,Retrofit默认使用OkHttpClient作为其CallFactory。

baseUrl 是Http请求的基址,在接口方法中指定的相对url和该字段拼接为一个完整的url,如示例中的https://api.example.com/

converterFactories 请求结果的转换器,通过该转换器可以将请求的结果转换成我们想要的数据格式或者对象。这是一个集合,可以添加多个转换器,接口方法根据其返回类型决定使用哪个转换器。

adapterFactories 请求适配器用来将生成的请求转换成平台需要的请求对象。

生成调用请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
//为Service接口类动态生成代理对象
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
@Override public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//接口方法的调用最终会通过代理对象来完成请求对象的生成
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}

create是retrofit最为精妙的部分,它结合了动态代理可以为每个接口方法生成对应的请求,事实上,这会经过以下几步完成:

  1. 根据调用的method方法来生成ServiceMethod,ServiceMethod是经过解析后的对象,它根据Method方法的注解来生成了一些创建OKHttpCall所需的信息。
  2. 结合解析后的Method对象即ServiceMethod和用户传递的方法参数生成OkHttpCall这是Retroift默认的请求对象
  3. 根据Method的返回类型ServiceMethod为Method创建适当的CallAdapter,通过该Adapter可以将创建的OkHttpCall转换成我们需要的Call请求。

针对接口方法生成ServiceMethod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//ServieMethod也是使用build模式来构建
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;//对应的Service方法
this.methodAnnotations = method.getAnnotations();//方法的注解
this.parameterTypes = method.getGenericParameterTypes();//参数类型
this.parameterAnnotationsArray = method.getParameterAnnotations();//参数注解
}

//为Service Method生成描述对象
public ServiceMethod build() {
callAdapter = createCallAdapter();//为方法的请求生成相应的适配器
responseType = callAdapter.responseType();//响应类型
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
responseConverter = createResponseConverter();//创建响应转换器
//解析方法注解
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
//根据解析结果得到的httpMethod不能为空
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}

if (!hasBody) {
if (isMultipart) { //multiPart注解必需要body的请求
throw methodError(
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {//FormUrlEncoded注解必需要body的请求
throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}

int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];

for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}

Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
//解析注解参数的值
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}

//如果没有设置相对url 则需要通过@Url指定
if (relativeUrl == null && !gotUrl) {
throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
}
//如果不是FormUrlEncoded或者MultiPart注解 就不需要@Body注解
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError("Non-body HTTP method cannot contain @Body.");
}

//如果提交Form需要至少一个@Filed注解
if (isFormEncoded && !gotField) {
throw methodError("Form-encoded method must contain at least one @Field.");
}
//如果是MultiPart需要至少一个@Part
if (isMultipart && !gotPart) {
throw methodError("Multipart method must contain at least one @Part.");
}
//为接口方法创建ServiceMethod对象
return new ServiceMethod<>(this);
}

生成Method对应的CallAdapter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private CallAdapter<T, R> createCallAdapter() {
Type returnType = method.getGenericReturnType();//取到返回类型
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {//返回类型不能为空
throw methodError("Service methods cannot return void.");
}
Annotation[] annotations = method.getAnnotations();//取到方法的注解
try {
//noinspection unchecked
//根据返回类型和注解返回相应的CallAdapter,这个CallAdapter用来将OkHttpCall转换为相应平台下的网络请求执行器
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}

生成Method对应的ResponseConverter,它负责将请求的结果进行格式转换。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private Converter<ResponseBody, T> createResponseConverter() {
Annotation[] annotations = method.getAnnotations();//获取注解
try {
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create converter for %s", responseType);
}
}

//转由retrofit处理,因为转换器都配置在这里
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}

//根据返回类型和注解取到转换器,skipPast为null
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {

int start = converterFactories.indexOf(skipPast) + 1;
//从converter集合列表中找到满足要求的转换器就返回,这里需要注意遍历是从集合首部开始,也就是说如果有两//个满足要求的转换器,先添加的转换器先匹配到。
for (int i = start, count = converterFactories.size(); i < count; i++) {
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
}
}

……
//未找到要求的抛出异常
throw new IllegalArgumentException(builder.toString());
}

解析Method注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) {//解析@DELETE注解
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {//解析@GET注解
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
} else if (annotation instanceof HEAD) {//解析@HEAD注解
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
if (!Void.class.equals(responseType)) {
throw methodError("HEAD method must use Void as response type.");
}
} else if (annotation instanceof PATCH) {//解析@PATCH注解
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {//解析@POST注解
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {//解析@PUT注解
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {//解析@OPTIONS注解
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
//解析@HTTP注解,表示一个自定义的HTTP请求,如:
// @HTTP(method = "GET", path = "xxx/", hasBody = false)
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError("@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
//解析@Multipart 表示请求体是多部分的。 每一部分作为一个参数,且用Part注解声明
if (isFormEncoded) {
throw methodError("Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
//解析FormUrlEncoded,表示请求正文将使用表单网址编码。使用FormUrlEncoded注解的请求将具”application / x-www-form-urlencoded” MIME类型
if (isMultipart) {
throw methodError("Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}

private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
if (this.httpMethod != null) {
throw methodError("Only one HTTP method is allowed. Found: %s and %s.",
this.httpMethod, httpMethod);
}
this.httpMethod = httpMethod;//HTTP method 只能有一个
this.hasBody = hasBody;//是否有body

if (value.isEmpty()) {//注解对应的参数
return;
}

// Get the relative URL path and existing query string, if present.
int question = value.indexOf('?');
if (question != -1 && question < value.length() - 1) {
// Ensure the query string does not have any named parameters.
String queryParams = value.substring(question + 1);
Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
if (queryParamMatcher.find()) {
throw methodError("URL query string \"%s\" must not have replace block. "
+ "For dynamic query parameters use @Query.", queryParams);
}
}

this.relativeUrl = value;//相对url
this.relativeUrlParamNames = parsePathParameters(value);//相对url中包含的请求参数
}

HTTP请求的创建

根据ServiceMethod创建OkHttpCall对象,这个代表一个http请求。这个OkHttpCall是Retrofit默认使用的请求对象,如果配置了callAdapterFactory则会通过相应的适配器工厂将该Call请求转换成我们需要的请求对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

final class OkHttpCall<T> implements Call<T> {
private final ServiceMethod<T, ?> serviceMethod;//service 接口方法的对象
private final @Nullable Object[] args;//网络请求调用的参数

private volatile boolean canceled;

@GuardedBy("this")
private @Nullable okhttp3.Call rawCall;//实际进行网络请求的的调用对象
@GuardedBy("this")
private @Nullable Throwable creationFailure; // Either a RuntimeException or IOException.
@GuardedBy("this")
private boolean executed;

OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}

前面我们知道Retrofit在配置过程中 即build时为Retrofit配置默认的CallAdapterFactory,这个是根据PlatForm来决定的,这里我们看看Android平台下它是怎样的一个Adapter。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

static class Android extends Platform {
//返回默认的回调执行器
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}

//Android平台下默认的请求适配工厂
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
//这里通过回调执行器来构造请求适配工厂
return new ExecutorCallAdapterFactory(callbackExecutor);
}

//结果回调执行器 用来将请求结果投递到主线程
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());

@Override public void execute(Runnable r) {
handler.post(r);
}
}
}

可以看出Android使用了ExecutorCallAdapterFactory,默认的callbackExecutor使用了MainThreadExecutor,它是一个回调执行器,用来将请求结果投递给主线程的,使用了Handler来投递Runable的方式来返回结果。接下来我们就重点分析下这个ExecutorCallAdapterFactory的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
final Executor callbackExecutor;

ExecutorCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}

//Retrofit使用get接口从工厂实例中取到CallAdapter
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}

@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}

static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor; //回调执行器,负责请求结果回调
final Call<T> delegate;//委托对象,这个对象负责HTTP请求的

ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}

//异步的请求方式
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");

delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
//回调执行器将结果回调给用户
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}

@Override public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}

……
//同步的请求方式
@Override public Response<T> execute() throws IOException {
return delegate.execute();
}

……
}
}

前面我们分析了为对应的接口方法生成ServiceMethod对象时,同时会为该对象指定一个CallAdapter,这个CallAdapter负责接口方法对应的请求及结果的回调,它是通过Retrofit的callAdapter来获取的,实际上是CallAdapterFactory的get接口从工厂实例中取到CallAdapter,CallAdapter只是一个接口,这里直接创建接口实例对象,其最重要的方法为adapt将请求的Call转换为平台下需要的call,这里我们看到它构造了ExecutorCallbackCall对象。

Http请求是委托给了adapt参数传递过来的Call,它是OkHttpCall负责HTTP请求的。Retrofit支持同步和异步的请求方式,对于异步的请求我们需要回调告诉用户请求结果成功与否,这是通过回调执行器来完成的。这里我们可以看到在CallBack的onResponse中通过callbackExecutor的execute投递请求结果,实际上是通过handler来进行的。这里总共有两个CallBack,第一个是用户传递给enqueue方法的,用户通过这个回调得到请求响应,第二个是用来响应委托请求的,而回调执行器就是在这两个接口之前负责线程切换。

对于同步的请求方式,就很简单了,它不需要回调调用后直接返回响应结果Response,但需要注意同步方式需在子线程使用。

请求过程

从CallAdapter中了解到,HTTP的请求是委托给了OkHttpCall的,因此下面我们需要进一步了解OkHttpCall是如何完成http请求的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
final class OkHttpCall<T> implements Call<T> {
private final ServiceMethod<T, ?> serviceMethod;//接口方法对应的对象
private final @Nullable Object[] args;//请求参数

private volatile boolean canceled;

@GuardedBy("this")
private @Nullable okhttp3.Call rawCall;//元请求对象 它才是实际上进行http请求的
@GuardedBy("this")
private @Nullable Throwable creationFailure; // Either a RuntimeException or IOException.
@GuardedBy("this")
private boolean executed;

OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}

从OkHttpCall的类结构我们大致了解OkHttpCall,它负责完成http请求则需要知道接口方法完成HTTP请求的参数以及HTTP请求的一些配置信息,因此我们需要serviceMethod和args,同时由于OkHttpCall它也是一个Call,我们需要控制请求过程,比如发起请求和取消请求。而rawCall看起来是负责OkHttpCall内部的http请求。我们继续看看execute方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//http的异步请求过程
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");

okhttp3.Call call;
Throwable failure;

//要加锁控制
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;

call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();//创建一个元请求
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}

if (failure != null) {
callback.onFailure(this, failure);//失败回调
return;
}

if (canceled) {
call.cancel();//取消请求的回调
}

//通过okhttp3完成的请求过程并通过回调相应
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
response = parseResponse(rawResponse);//解析相应结果
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);//通过callback回调给调用者
}

@Override public void onFailure(okhttp3.Call call, IOException e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}

private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}

private void callSuccess(Response<T> response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}

//同步请求过程
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;

synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;

if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw (IOException) creationFailure;
} else {
throw (RuntimeException) creationFailure;
}
}

call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}

if (canceled) {
call.cancel();
}

return parseResponse(call.execute());
}

可以看出实际上进行请求的Call是通过createRawCall创建的,我们看看它的实现

1
2
3
4
5
6
7
8
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}

可以看到createRawCall是通过callFactory来创建实际请求的Call的,这个callFactory是在Retrofit中进行配置的,Retrofit倾向于使用OkHttp,它提供了client接口来配置OkHttpClient,它是一个基于OkHttp的call Factory,当然Retrofit同样支持其他的请求库,这也是它为什么会有callFactory的原因。我们完全可以封装HttpUrlConnection作为Retrofit的Call Factory,并通过builder的callFactory方法进行配置,它同volley一样是可以配置自身的请求库的,从这个角度来说Retrofit是比较开放和包容的library。这里我就不继续分析OkHttpClient具体的请求过程了,在介绍OkHttp时再做介绍,感兴趣的童鞋可以自行查看。

请求结果的转换

在上一部分内容中请求的结果最终是送给parseResponse进行处理的,从名称来看它负责解析响应的内容。我们看看它的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();//得到ResponseBody

// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();

int code = rawResponse.code();//得到响应码
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}

if (code == 204 || code == 205) {
rawBody.close();
return Response.success(null, rawResponse);
}

ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
//这里对请求结果进行转换
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}

paserResponse通过请求响应rawResponse构造Response,这里面首先取到响应的ResponseBody,然后构造一个body为空的Response,这个Response只有状态,为什么这么做可能是因为转换后的Response本身就包含了响应内容的,在rawResponse再包含相同的数据传递就没必要了,尤其是当数据内容较大时。随后会根据得到的响应码来做不同的处理,最终会通过Response的success或者error构造Response对象返回给调用者。在最后调用Response的success之前会调用serviceMethod的toResponse对响应内容进行转换。

1
2
3
4
/** Builds a method return value from an HTTP response body. */
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}

可以看到ServiceMethod的toResponse实际上是通过我们配置的转换器调用convert来完成数据转换的,这里就是将ResponseBody转换成接口方法的返回类型。Retrofit内置了几种转换器,它是通过BuiltInConverters来实现的,这里看看最常用的一种转换器的实现即将ResponseBody转换为Gson对象,实际上我们为Retrofit配置的Converter Factory支持请求和响应的转换,这里我们看看响应转换即GsonResponseBodyConverter的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;

GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}

@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
return adapter.read(jsonReader);
} finally {
value.close();
}
}
}

转换是通过ResponseBody的字符流来构造JsonReader对象来完成的,具体过程就不分析了。

到这里我们基本上就分析完Retrofit的结构了,从整体的结构来说Retrofit的架构比较简单和直接,代码结构也非常清晰和易读,这是一个优秀框架难得的部分。内部使用了大量的设计模式来解耦,如工厂模式,代理模式,以及装饰模式,适配模式等等,这些设计模式带来的优势也是非常明显的,既使得代码结构清晰,也增强了可拓展性。

总结

Retrofit本质上是一个Restful API的网络请求库,它将http请求封装成接口,通过注解的方式来修饰方法和参数以配置Http请求,内部通过动态代理来生成Http请求的Call对象,生成过程首先通过解析接口方法得到ServiceMethod对象并缓存到Map中,
通过该对象构造一个OkHttpCall,这个负责http的请求,随后通过callAdapter将该请求进行封装和适配以满足PlatForm的要求,在这个过程中异步请求会将Call和callbackExecutor关联起来,以在请求后将结果通过回调执行器投递给调用者。请求完成后通过配置的转换器将响应内容转换为需要的格式。

坚持原创技术分享,您的支持将鼓励我继续创作!